﻿using System;
using System.Collections.Generic;
using System.Composition;
using System.Events;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Data.Xml.Dom;
using Windows.Foundation;
using Windows.UI.Notifications;

namespace Windows.UI.Notifications
{
    
    [Shared]
    [MessageRecipientExport("ToastNotificationMessageProcessor", typeof(CreateToastNotificationMessage))]
    //[PartMetadata("Name", "ToastNotificationMessageProcessor")]
    //[PartMetadata("MessageType", typeof(CreateToastNotificationMessage))]
    //[Export(typeof(IMessageRecipient))]
    public class ToastNotificationMessageProcessor : IMessageRecipient
    {
        //[Import(typeof(IEventPublisher), AllowDefault = true)]
        private IEventPublisher messenger;// { get; set; }
        
        [ImportingConstructor]
        public ToastNotificationMessageProcessor([Import]IEventPublisher msgr)
        {
           messenger = msgr;
        }

        #region Privates

        private XmlDocument PrepareToastXml(ToastTemplateType templateType, string toastImageSrc, bool loopAudio = false,
            string AudioSrc = "ms-winsoundevent:Notification.IM", params string[] message)
        {
            XmlDocument toastXml = ToastNotificationManager.GetTemplateContent(templateType);
            if (!string.IsNullOrEmpty(toastImageSrc))
            {
                XmlNodeList imageElements = toastXml.GetElementsByTagName("image");
                XmlElement imageElement = (XmlElement)imageElements.Item(0);
                imageElement.SetAttribute("src", toastImageSrc);
                imageElement.SetAttribute("alt", "Placeholder image");
            }
            XmlNodeList textElements = toastXml.GetElementsByTagName("text");
            uint textElementsCount = Math.Min((uint)message.Length, textElements.Length);
            for (uint i = 0; i < textElementsCount; i++)
            {
                textElements.Item(i).AppendChild(toastXml.CreateTextNode(message[i]));
            }
            if (!string.IsNullOrEmpty(AudioSrc))
            {
                XmlElement audioElement = toastXml.CreateElement("audio");
                audioElement.SetAttribute("src", AudioSrc);
                audioElement.SetAttribute("loop", loopAudio.ToString());
                toastXml.AppendChild(audioElement);
            }

            return toastXml;
        }

        private ToastNotification Show(
            ToastNotifier notifier,
            ToastTemplateType templateType = ToastTemplateType.ToastImageAndText04,
            string toastImageSrc = null,
            bool loopAudio = false,
            string AudioSrc = "ms-winsoundevent:Notification.IM",
            int ShowDuration = 1,
            TypedEventHandler<ToastNotification, object> onActivated = null,
            TypedEventHandler<ToastNotification, ToastDismissedEventArgs> onDismissed = null,
            TypedEventHandler<ToastNotification, ToastFailedEventArgs> onFailed = null,
            params string[] message)
        {
            XmlDocument toastXml = PrepareToastXml(templateType, toastImageSrc, loopAudio, AudioSrc, message);

            ToastNotification toast = new ToastNotification(toastXml);

            toast.ExpirationTime = DateTimeOffset.UtcNow.AddSeconds(ShowDuration);

            if (onActivated != null)
                toast.Activated += new TypedEventHandler<ToastNotification, object>(onActivated);
            if (onDismissed != null)
                toast.Dismissed += new TypedEventHandler<ToastNotification, ToastDismissedEventArgs>(onDismissed);
            if (onFailed != null)
                toast.Failed += new TypedEventHandler<ToastNotification, ToastFailedEventArgs>(onFailed);

            notifier.Show(toast);

            return toast;
        }

        private void Show(
            ToastNotifier notifier,
            string tag,
            ToastTemplateType templateType = ToastTemplateType.ToastImageAndText04,
            string toastImageSrc = null,
            bool loopAudio = false,
            string AudioSrc = "ms-winsoundevent:Notification.IM",
            int ShowDurationOffset = 5,
            int DisplayInterval = 1,
            uint MaxDisplayCount = 3,
            params string[] message)
        {
            XmlDocument toastXml = PrepareToastXml(templateType, toastImageSrc, loopAudio, AudioSrc, message);

            // Use the DateTimeOffset type to specify the display time
            DateTimeOffset displayTime = DateTimeOffset.UtcNow.AddSeconds(ShowDurationOffset);
            // interval must be at least 60 seconds
            TimeSpan interval = TimeSpan.FromMinutes(DisplayInterval);
            ScheduledToastNotification scheduledToast = new ScheduledToastNotification(toastXml, displayTime, interval, MaxDisplayCount);
            // You can specify an ID so that you can manage the scheduled toasts later
            // The ID needs to be 15 characters or less
            scheduledToast.Id = tag;
            // The toast notifier object is used to manage scheduled toasts

            notifier.AddToSchedule(scheduledToast);
        }
        #endregion

        public void ProcessMessage(CreateToastNotificationMessage message)
        {
            var data = message.Content;

            ToastNotifier tn = ToastNotificationManager.CreateToastNotifier(); //data.ApplicationId
            //var tn = message.Content.Notifier;
            Show(tn, data.TemplateType, data.ImageSrc, data.LoopAudio, data.AudioSrc, data.ShowDuration,
                (n, ea) => messenger.Publish<ToastActivatedMessage>(new ToastActivatedMessage(){ Data = data, Notification = n }),
                (n, ea) => messenger.Publish<ToastDismissedMessage>(new ToastDismissedMessage() { Data = data, Notification = n, Reason = ea.Reason }),
                (n, ea) => messenger.Publish<ToastFailedMessage>(new ToastFailedMessage() { Data = data, Notification = n, Error  = ea.ErrorCode }),
                data.Message);
        }

        public void ProcessMessage(object message)
        {
            if(message is CreateToastNotificationMessage)
                ProcessMessage((CreateToastNotificationMessage)message);
        }

        [OnImportsSatisfied]
        public void OnImportsSatisfied()
        {
        }

    }
}
